package com.ruoyi.common.imgconflate.jai;

import lombok.extern.slf4j.Slf4j;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

/**
 * 生成签到图片工具类
 */
@Slf4j
public class GenerateAttendanceImageUtil {
    private static int y = 0;

    /**
     * 生成签到页图片（PNG格式）
     *
     * @param backgroundImage 背景图片
     * @param title           会议主题配置
     * @param qrCodeImgCfg    二维码图配置
     * @param outputFile      图片输出位置
     */
    public static void createCompositeImage(File backgroundImage, TextConfig title,QrCodeImageConfig qrCodeImgCfg, File outputFile) {
        try {
            // 加载背景图片
            BufferedImage bgImgBuffer = ImageIO.read(backgroundImage);
            Graphics g = bgImgBuffer.getGraphics();

            // 插入文字准备
            Graphics2D g2d = (Graphics2D) g;
            g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

            // 插入会议主题
            y = title.getY();
            drawString(title, g, g2d, bgImgBuffer.getWidth() - title.getX(), false);


            // 插入二维码
            y = Math.max(y + 30, 310);
            g.drawImage(qrCodeImgCfg.getQrCodeBuffer(), (bgImgBuffer.getWidth() - qrCodeImgCfg.getWidth()) / 2, y, null);


            g.dispose();
            // 将结果保存为新的图片
            ImageIO.write(bgImgBuffer, "png", outputFile);
        } catch (IOException e) {
            log.error(e.getMessage());
        } finally {
            if (qrCodeImgCfg.getQrCodeImgFile().exists()) {
                boolean delete = qrCodeImgCfg.getQrCodeImgFile().delete();
                if (!delete) {
                    log.error("GenerateAttendanceImageUtil.createCompositeImage finally 二维码图片删除失败");
                }
            }
        }

    }

    /**
     * 绘制文字
     */
    private static void drawString(TextConfig textConfig, Graphics g, Graphics2D g2d, Integer bgImgWidth, boolean horizontalCenter) {
        g.setFont(new Font(textConfig.getTypeface(), textConfig.getBoldFont() ? Font.BOLD : Font.PLAIN, textConfig.getFontSize()));
        g.setColor(textConfig.getFontColor());

        FontMetrics fm = g2d.getFontMetrics();
        int lineHeight = fm.getHeight();
        int x = horizontalCenter ? (bgImgWidth - fm.stringWidth(textConfig.getText())) / 2 : textConfig.getX();
        int lingNum = 1;
        for (String text : convertToArray(textConfig.getText())) {
            int textWidth = lingNum > 4 ? fm.stringWidth(text + "...") : fm.stringWidth(text);
            boolean needTrim = false;
            // 最多显示5行超出部分省略
            if (x + textWidth > bgImgWidth) {
                if (lingNum >= 5) {
                    g2d.drawString("...", x, y);
                    break;
                }

                // 符号截留在上一行，不做下一行的首字母
                if (!Character.isLetterOrDigit(text.charAt(0)) && !Character.isWhitespace(text.charAt(0))) {
                    g2d.drawString(text, x, y);
                    continue;
                }
                x = textConfig.getX();
                y += lineHeight + textConfig.getLineSpacing();
                needTrim = true;
                lingNum++;
            }
            // 取消换行后首字母的空格
            if (needTrim && text.equals(" ")) {
                continue;
            }
            g2d.drawString(text, x, y);
            x += fm.stringWidth(text) + textConfig.getWordSpace();
        }
    }

    /**
     * 判断是否为英文或数字
     */
    private static boolean isLetterOrNumber(char c) {
        String character = String.valueOf(c);
        return Pattern.matches("[a-zA-Z0-9]", character);
    }

    /**
     * 将字符串拆分成最小单元
     */
    public static String[] convertToArray(String input) {
        List<String> resultList = new ArrayList<>();
        for (int i = 0; i < input.length(); i++) {
            char s = input.charAt(i);
            if (isLetterOrNumber(s)) {
                StringBuilder sb = new StringBuilder();
                while (i < input.length() && isLetterOrNumber(input.charAt(i))) {
                    sb.append(input.charAt(i));
                    i++;
                }
                i--;
                resultList.add(sb.toString());
            } else {
                resultList.add(String.valueOf(s));
            }
        }
        return resultList.toArray(new String[0]);
    }
}
